package com.hnld.transform.util;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;

public class FindChildrenClassUtil {

    public static <T> Map<String, T> findImplementations(Class<T> t, String methodName) throws Exception {
        Map<String, T> map = new HashMap<>();
        String packageName = t.getPackage().getName();

        // 反射查找特定包下所有类，检查是否实现了接口
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String path = packageName.replace('.', '/') + "/impl";
        Enumeration<URL> resources = classLoader.getResources(path);
        List<File> dirs = new ArrayList<>();
        while (resources.hasMoreElements()) {
            dirs.add(new File(resources.nextElement().toURI()));
        }

        for (File directory : dirs) {
            Class<?> clazz;
            for (File file : directory.listFiles((d, name) -> name.endsWith(".class"))) {
                clazz = classLoader.loadClass(packageName + ".impl." + file.getName().replace(".class", ""));
                if (t.isAssignableFrom(clazz)) {
                    Method method = clazz.getMethod(methodName);
                    map.put(method.invoke(clazz.newInstance()).toString(), (T) clazz.newInstance());
                }
            }
        }

        return map;
    }

}
